/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "myled.h"
#include "stdio.h"
#include <string.h>
#include "FreeRTOS.H"
#include "task.h"
#include "queue.h"
#include "semphr.h"   /*信号量.h*/
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* 句柄 */
TaskHandle_t  Task1handle;
TaskHandle_t  Task2handle;


/*任务通知轻量级事件组测试*/
TaskHandle_t  Task3handle;
TaskHandle_t  Task4handle;
TaskHandle_t  Task5handle;

/*队列句柄*/
QueueHandle_t Queue1;

/*信号量句柄*/
SemaphoreHandle_t Sem1;
/*互斥量句柄*/
SemaphoreHandle_t Sem2;
#define Tstate 2  /*任务通知0为轻量级信号量 1为队列 2为事件组*/ 
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

int fputc(int ch , FILE *f )
{
	 while((USART2->SR & (1<<7))==0);
	 USART2->DR=ch;
	 return ch;
}

#if Tstate==2
/*
任务3和4都使用了串口打印，(时间不同可以不加上互斥锁)
但加上互斥锁能防止资源被打断，数据错乱，更稳定
由于任务3和4的执行时间不同所以会有一个先唤醒任务5
*/
  void task3_function(void * ch)
{ 
	  int sum=1;
		while(1)
		{
				for(int i=0;i<100000;i++)
				sum++;
			  xQueueSend(Queue1,&sum,0);
			  xTaskNotify(Task5handle,(1<<0),eSetBits);
			  //xSemaphoreTake(Sem1,portMAX_DELAY); /*使用信号量做互斥锁（无初始值）*/
			  xSemaphoreTake(Sem2,portMAX_DELAY);   /*使用互斥量做互斥锁（有初始值1）*/
			  printf("task3 send off\r\n");
			  //xSemaphoreGive(Sem1);
			  xSemaphoreGive(Sem2);
			  vTaskDelete(NULL);
		}
}
/*任务4先执行*/
	void task4_function(void * ch)
{  
	  int sum=-1;
		while(1)
		{
				for(int i=0;i<1000;i++)
				sum--;
			  xQueueSend(Queue1,&sum,0);
			  xTaskNotify(Task5handle,(1<<1),eSetBits);
			  //xSemaphoreTake(Sem1,portMAX_DELAY); /*使用信号量做互斥锁（无初始值）*/
			  xSemaphoreTake(Sem2,portMAX_DELAY);   /*使用互斥量做互斥锁（有初始值1）*/
			  printf("task4 send off\r\n");
			  //xSemaphoreGive(Sem1);
			  xSemaphoreGive(Sem2);       
			  vTaskDelete(NULL);
		}	
}
	void task5_function(void * ch)
{ 
  int val1,val2;	
	uint32_t stbit;
	while(1)
	{
	   xTaskNotifyWait(0,0,&stbit,portMAX_DELAY);
		 vTaskDelay(5);
  	 if((stbit & 0x3)==0x3)
		 { 
			 xTaskNotifyWait(0x03,0,&stbit,0);/*手动清除，输入前清除*/
		   xQueueReceive(Queue1,&val1,0);
			 xQueueReceive(Queue1,&val2,0);
			 printf("%d |%d \r\n",val1,val2);
		 }
		 else 
		 { 
		   printf("NO ALL\r\n");
		 }
		 
	}
}
#else
/*轻量级信号量*/
void task1_function(void)
{ 
	  int val;
		while(1)
		{
#if Tstate==0
        for(int i=0; i<100000;i++)
			  sum++;
  			for(int i=0;i<10;i++)
			  xTaskNotifyGive(Task2handle);//任务通知写入信号量
			  vTaskDelete(NULL);//任务自杀
#elif Tstate==1
			   for(int i=0; i<100000;i++)
			   sum++;
			   for(int i=0;i<10;i++)
			   {
			    xTaskNotify(Task2handle,sum,eSetValueWithOverwrite);
					 /*
					 任务通知写入数据（不覆盖）数据发一次为100000
					 覆盖为100009
					 */
			    sum++;
				 }
			   vTaskDelete(NULL);//任务自杀
#endif
			  
		}
}
void task2_function(void)
{  
	  uint32_t val;
		while(1)
		{
#if Tstate==0
			val=ulTaskNotifyTake(pdFALSE,portMAX_DELAY);
			/*
			获取任务通知值 pdTRUE为全清除(take一次，仅输出10，输出清除前的数据)，
			pdFALSE为val--，即为输出10到1；10个数据。			
			*/
			printf("%d  %d\r\n",sum,val); 
#elif Tstate==1
        xTaskNotifyWait(0,0,&val,portMAX_DELAY);//获取轻量级队列值
			  printf("%d\r\n",val);
#endif			
		}
}
#endif


/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  myled_config();
	Queue1=xQueueCreate(2,sizeof(int));/*创建队列*/
	Sem1=xSemaphoreCreateBinary();     /*创建信号量*/
	xSemaphoreGive(Sem1);
	Sem2=xSemaphoreCreateMutex();      /*创建互斥量*/
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

//  xTaskCreate((TaskFunction_t )LED1_task,            //任务函数
//              (const char*    )"LED1_task",          //任务名称
//              (uint16_t       )128,                  //栈大小
//              (void*          )NULL,                 //传入参数
//              (UBaseType_t    )0,                 //优先级
//              (TaskHandle_t*  )&LED1Task_Handler);   //任务句柄        
							
#if Tstate==2

			
			xTaskCreate((TaskFunction_t )task3_function,"task3",128,NULL,1,&Task3handle);   //任务句柄
			xTaskCreate((TaskFunction_t )task4_function,"task4",128,NULL,1,&Task4handle);   //任务句柄  
			xTaskCreate((TaskFunction_t )task5_function,"task5",128,NULL,2,&Task5handle);   //任务句柄 
#else 
//			xTaskCreate((TaskFunction_t )task1_function,"task1",128,NULL,0,&Task1handle);   //任务句柄  
//			xTaskCreate((TaskFunction_t )task2_function,"task2",128,NULL,0,&Task2handle);   //任务句柄  
#endif	

	
  vTaskStartScheduler();                             //启动调度器                    
   
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 90;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
